SpotCheck


GenieWorks, LLC

Introduction

SpotCheck is a language-based editor, or structure editor, that "knows" the Java language. It is designed to help a novice Java programmer produce correct code, without relying on confusing and un-timely feedback from a compiler. SpotCheck helps you learn Java, or use parts of the language you don't commonly use, by showing you exactly what's syntactically possible at each juncture, and allowing you to choose. SpotCheck also identifies common semantic errors (undefined names, type mismatches, etc.), and the set of error checks available will grow with each release. This semantic analysis is performed "incrementally", after each edit, giving the programmer immediate feedback on errors. This and many other "convenience"features of SpotCheck will make even expert programmers find it an appealing environment for creating Java code.

SpotCheck is not yet a complete programming environment, as it relies on external support applications to compile Java source to class files. Nonetheless, we have made every effort to make the compilation interface as transparent as possible. As of this writing, SpotCheck has built-in AppleEvent interfaces to Metrowerks' CodeWarrior and Sun's Mac JDK 1.0.2, with interfaces for Symantec's Cafe and Natural Intelligence's Roaster planned.

The remainder of this README file functions as a limited User's Manual. However, most of the information here is better presented in our new Tutorial document. We highly recommend that you start there. There are still a few topics that are explained in more detail here, if you should need more information than the tutorial provides.

Scene Roots and the Browser

Scene roots are large sections of code that are elided, or abbreviated. The bulk of the code is replaced with a "Go In" button. Simply double-click on the button to see the rest. The entire "scene"you were just viewing will be replaced by the expanded class declaration, method declaration or whatever. To return, use "Go Back" or "Go Out" in the "Find" menu. "Go In" and "Go Out" have keyboard equivalents that aren't shown in the menu, <command>-<down arrow> and <command>-<up arrow>, respectively.

The "scene roots" form a course-grained hierarchy in the project. The browser panes at the top of the window allow you to navigate this hierarchy of packages, classes, etc. Single clicks suffice in the browser. Note that there is a top-level "project scene" that has no browser entry associated. You can access this scene using "Go To Project" in the "Find" menu, repeated uses of <command>-<up arrow>, or a single lt;command>-<shift>-<up arrow>.

Structure Editing

SpotCheck is first and foremost a structure editor, but it also has a text-editing mode. The two modes are clearly differentiated visually, but there is a way to maximize that differentiation. If you have a color or grayscale monitor, make sure that your highlight color (in the Color control panel) is NOT "Black & White". SpotCheck uses inverse video (white text on black) for the selection in structure mode, and your highlight color for the selection in text mode. Text mode is also distinguished by an outlined box corresponding to the last structure selected. The sooner you learn to distinguish which mode you are in, the happier you will be.

In structure mode, you edit the program using "point and click". Portions of the program that have not been filled in yet are shown as "placeholders", indicated by $-signs at each end. When you start SpotCheck, it opens the Default stationery document, and asks you where you want to save your new copy. Once you've saved the copy, you will see:


Select (click once on) "YourAppletAsApp", and hit the delete key. You will now see:


There is a single placeholder here: "$the_name$". The small triangle next to it indicates a popup menu... click and hold over the triangle, and a menu of legal replacements for the placeholder appears. For this placeholder, there is only one choice, "thisClassOrInterface". When you select that choice, you will be dropped into text-editing mode at that location, so you can type in an identifier. This happens in general, whenever you select a choice that represents an identifier or literal value.

The popup menu for the current placeholder selection is also available in the menu bar, as the "Construct" menu. The contents of this menu change depending on what sort of placeholder is currently selected. If the selection is not a placeholder, the "Construct" menu disappears.

The construct mode editing commands can be found in the Edit menu, with their keyboard equivalents. There are, however, two shortcuts that are not indicated in the menu. First, <return> is an alternative for "Extend After", and is available in the same situations. This is convenient for entering lists of statements, for example. Second, <space bar> can be used to cycle through the possibilities at a particular selection. This is most useful when the number of possibilities is small, e.g. "public / private / protected". Nonetheless, you can use it if you wish to explore the possibilities for $statement$. Note that whatever syntax was originally present at the selection will be lost. Note also that <space bar> will present dummy values for identifiers and literals, and these are almost never useful.

Sprinkled throughout the code you will find little open circles. These are simply "holes" for optional parts of the code that are currently missing. Double-clicking on a "hole" will replace it with the optional syntax, possibly just a placeholder. The <delete> key will also have this effect on a "hole".

Normally you will move the structural selection by clicking (and possibly dragging) with the mouse. A single click will select the nearest treenode (going "up" the tree toward the root) whose "unparse area"includes the click point; that is, the "smallest" subtree containing the click. Click and drag will select the smallest subtree that includes both the start and end points of the drag. If you hold down the option key while you drag, the selection will remain the smallest one containing the current mouse point. This is a convenient way to familiarize yourself with the structure of the abstract syntax tree.

You can also "navigate" using the arrow keys. The arrow keys provide screen-oriented up-down-left-right navigation. If modified with the <option> key, they provide navigation through the abstract syntax tree:

option-left-arrow "go left to sibling"
option-right-arrow "go right to sibling"
option-up-arrow "go to parent"
option-down-arrow "go to first son"

The option-arrow keys are particularly useful when you can't seem to select what you want with the mouse. If you can't get it with the arrow keys, then you are attempting to select a chunk of syntax that is not represented as a single tree node (or range of list members), which is not possible in structure mode.

The arrow keys can also be modified with the <shift> key, to add to the current selection. The resultant selection will be the smallest that contains both the starting point and the item that would have been selected by the un-shifted arrow key.

There is one additional shortcut for local tree navigation: the <tab>key takes you to the next "choice point", the next structural selection that can be deleted or replaced. In technical terms, this basically amounts to a pre-order traversal of the tree. In practical terms, it's a more useful alternative to "option right arrow", which cannot fill the same need without the assistance of "option up-arrow"and "option-down-arrow". It's also useful in that it stops at "holes", which will be skipped by <command>-J, "go to next placeholder". You will find that you can do quite a bit of editing using simply two keys, <tab> and <space bar>, subject to the limitations of the latter discussed above.

Text Editing

When you are in text-editing mode, the current structural selection is surrounded by a box, and within that box is editable text (with its own selection or "I-bar" cursor). To cancel text-editing mode, type <command>-<period>... the program will remain unchanged. To leave text-editing mode normally (causing the new text to be parsed in context), type <enter>, <tab>, or <command>-T, or click once outside of the text edit box anywhere that the "+" cursor shows. Many users find <tab> to be the most convenient, and even intuitive, since it effectively "goes to the next entry field".

You can enter text-edit mode on any selection using <command>-T ("Edit as Text" in the "Edit" menu), or <enter>. You can also accomplish this simply by starting to type over a placeholder. (This will work for any selection, if your editing preference is set for this behavior. Note that the text of the selection will be replaced with your first keystroke.) Finally, double-clicking on most selections will enter text-editing mode. The exceptions are scene roots, described below, and "read-only" syntax, such as the package statement shown at the beginning of each .java file.

SpotCheck's parser is fairly clever, and is able to parse partial input as long as there is no error. You can take advantage of this behavior to accelerate entry of your code. For instance, if your current selection is a statement placeholder, you may simply type "for", followed by <tab> or <enter>, and an entire for-statement will appear, with placeholders for the unspecified pieces. At this point, the structure selection will be the first placeholder in the for-statement, so you can immediately type "int i=0", or whatever. Of course, you can just as easily type in "for( int i=0;" <tab>, and the results will be the same.

The parser will also accept placeholders in input text. In fact, it will accept any string of text between two '$' characters... even "$$"is allowed. Any such placeholder token can "stand in" wherever any kind of placeholder is allowed. This is usually an advantage, but it can also cause problems for partial parsing. As an illustration, consider the partial input, "$XXX$", typed on a statement placeholder. There are several possible syntactic constructs that can begin with a placeholder in this context, and the parser must arbitrarily select one. That's OK, as long as the choice made is the one you intended, but it's inconvenient otherwise. "Undo" comes in handy here.

SpotCheck's parser will rearrange some array declarations. SpotCheck displays array variable declarations with the brackets next to the type, rather than using the old C/C++ style:

"int[][] anArray" versus "int anArray[][]"

However, SpotCheck's parser will accept the old style. If multiple declarators appear separated by commas, with differing numbers of trailing "[]"pairs, SpotCheck will create additional variable declaration lines as needed, collecting all variables with the same array "depth" in one declaration.

Semantic Analysis and Error Tags

After each user editing operation, SpotCheck will incrementally update its "database" of semantic information. The most visible effect of this update will be the appearance or disappearance of "error tags"or "blobs" in the code. A blob is displayed as a red (option-8), and signifies that the indicated piece of code is in violation of the Java language specification. In short, SpotCheck is performing many of the checks that the Java compiler will perform eventually, but SpotCheck is performing them immediately.

This is not to say that SpotCheck is an incremental compiler . No code is being generated. When all the semantic tests have been implemented (only a few are, as yet), any piece of code that has no blobs present will pass the compilers checks with flying colors. Effectively, the Java compiler will simply be performing code generation.

Blobs are not simply inert visual noise; double-clicking on a blob will bring up the error dialog, with an error message displayed within. Eventually, we intend to provide much more information in the error dialog, including "live" URLs to the language specification, online documentation, or tutorials, and even options to apply automatic "fixes" to common errors.

Blobs are also useful as "bookmarks" for incomplete code, a way to let SpotCheck remember "what I haven't done yet". The most common blob is the "undeclared identifier" error tag, which is particularly useful in this regard.

As you might imagine, error tags are not the only use for the semantic information maintained by SpotCheck. At any identifier reference site, you can use "Go To Declaration" (in the "Find" menu) to navigate directly to the declaration site for that identifier. Of course, that operation will be unavailable if the identifier is not declared, or if some other error prevents it from being bound to a declaration site. (E.g., in " foo .bar", since "foo" is not declared, "bar" cannot be looked up at all.) Also in the "Find"menu is the "Change Decl & Refs" command, which allows you to simultaneously change an identifier declaration and all the identifier reference sites currently bound to it. Note that some reference sites might not stay bound after the change, if there is an existing declaration with the same name that masks the renamed declaration.

Package Libraries

"Package java" is a package library document , and must be present in the same folder as the SpotCheck application. Package library documents and normal SpotCheck project documents use exactly the same format on disk, but package library documents are displayed differently and do not allow compilation. They exist merely to provide a semantic infrastructure for your projects. As such, they need not include any executable code, nor private members.

SpotCheck supports package and import semantics exactly as described by the Java language specification. An imported package can be found in any open package library document, or in the document containing the importing .java file. Imported packages are looked up by name, starting with top-level names. Note that any SpotCheck project document can contain named packages as well as .java files that belong to the unnamed, "default"package. In SpotCheck, a given .java file is a member of a given package by virtue of being physically contained within the package. Use the "Go To Project" command to see how packages and .java files are organized in a SpotCheck project document. Note also that "import p1.p2.C3"will work only if both "package p1" and "package p1.p2" are defined. Top-level packages like "p1" need not contain any .java files, but they must exist in some open SpotCheck document.

SpotCheck automatically opens the "package java" library document on each startup, and it is not closed until SpotCheck quits again. This document contains version 1.0.2 of the standard API classes, including packages java.lang, java.awt, and java.applet, and the rest. You should never move or rename the document so that SpotCheck won't find it on startup . Note also that "package java" is a very large document, but it is hardly ever read into memory in its entirety.

Although SpotCheck is designed to support dependencies on (imports from) multiple package library documents, that mechanism is not yet operative as of this writing. As such, if your project document needs to import a class from some package other than those found in "package java", you have two options, neither of which are entirely satisfactory. First, you can simply ignore the blobs that are present because SpotCheck cannot find the package you are importing. The problem here, of course, is knowing which blobs are due to the missing package and are therefore safe to ignore. As an alternative, you can add the appropriate named packages, with whatever class, interface, and member declarations your project requires, within your project document . If you have included all the necessary declarations, there should be no unnecessary blobs. However, when you compile your project, SpotCheck will generate .java files for the library packages you've defined, and will include those files in the compilation.


Compiling and Executing

The "Project" menu is largely self-explanatory, but there are a couple of things that must be explained about the compilation interface. Most important is the basic organization of a SpotCheck project document. Each such document can contain many ".java file" components. These are not actually separate files; all the information is contained within the same project document. Nonetheless, the external compiler applications require individual text files, so SpotCheck generates these text files as needed.

When you execute one of the compile commands ("Build and Run Project", "Compile Project", or "Compile .java File"), SpotCheck will first make sure that all the changed ".java file" components of your project will be written to disk as individual text files. SpotCheck remembers which of the internal "files" have been changed since the last compile, and avoids re-creating disk versions of unchanged .java files. You can force all .java files to be recreated on disk using the "Touch All Files" command before compiling.

Using CodeWarrior to Compile

CodeWarrior has the curious feature that it requires the Apple Script system extension to be loaded before it will respond to AppleEvents. If SpotCheck can find and launch CodeWarrior, but can't seem to make it do anything, you may need to install Apple Script and restart your Mac.

We have tried to isolate SpotCheck users from the complexities of using CodeWarrior as much as possible. In doing so, we have chosen a particular set of project settings for CodeWarrior Java projects created automatically by SpotCheck. You may find that these settings are not quite what you need. If so, you can simply make the necessary adjustments after SpotCheck has directed CodeWarrior to create the project. (SpotCheck does this automatically, the first time you compile your project.)

SpotCheck's default project document is for an Applet subclass that also has a static "main" method, allowing it to be run as a standalone application. The CodeWarrior project settings have been tuned for this default, creating a "Runable Zip File". SpotCheck will set the "File Name" and "Main Class" automatically, using the name of your SpotCheck project document minus the ".spot" extension. The name of the CodeWarrior project document itself is set according to a similar convention; if you change this name by hand, SpotCheck will be unable to find the project to compile.

After SpotCheck sends the "compile" AppleEvent to CodeWarrior, it waits for a response. The response event either will indicate success, or will contain a list of error messages. In the latter case, SpotCheck unpacks these and provides a simple "compiler error dialog" for browsing through the errors, selecting the closest bit of syntax for display. You can close the compiler error dialog, and reopen it with "Show Errors".

SpotCheck cannot tell (presently) if you have edited the on-disk .java text files, for example if you used CodeWarrior to browse through and fix any errors reported after an attempted compilation. As such, unless you remember to make the same changes within the SpotCheck project document, your changes will be lost the next time SpotCheck regenerates the .java text files. We recommend making all your changes within SpotCheck.

Another problem arises if CodeWarrior's "Message Window" has the lower pane open, showing the code for each error message listed in the upper pane. If that is the case, the .java text file being displayed is open in CodeWarrior, and SpotCheck will be unable to overwrite that file on the next compile. If you toggle the lower pane closed (using the little triangle on the left), there will be no problem.

Compiling with Sun's JDK

JDK has no project documents, so compilation is a good deal simpler that it is using CodeWarrior. There are only a few wrinkles. First, if your project contains several .java files, they often need to be compiled at the same time. Rather than attempting to be too clever just yet, SpotCheck simply simulates dragging dropping all your .java files onto the Java Compiler, regardless of whether you indicated "Compile Project"or "Compile .java File".

The "Build & Run Project" command does not function as advertised... it will only run the project. You must compile the project explicitly before executing it.

If you use JDK, you may have discovered the settings that make the compiler run faster. We find using the Java Compiler much more pleasant if we disable threaded compiles, debugger info, and code optimization. See the "Properties..."command in the "File" menu of the Java Compiler application. Be sure to hit the "OK" button to make your changes permanent.